﻿using System;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Xml;
using System.Configuration;
using System.Globalization;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Net.Mail;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text.RegularExpressions;

namespace EvolSoftWeb
{
    /// <summary>
    /// Descripción: Clase que contiene funcionalidades comunes de las aplicaciones
    /// </summary> 
    public static class Tools
    {

        /// <summary>
        /// Enviar un correo a un conjunto de destinatarios
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        public static void SendEmail(string mailTo, string mailCc, string subject,
            string body)
        {
            MailMessage correo = new MailMessage();

            correo.From = new MailAddress(ConfigurationManager.AppSettings[DatosCorreo.MailFrom]);
            correo.To.Add(mailTo);
            if (!string.IsNullOrEmpty(mailCc))correo.CC.Add(mailCc);
           
            correo.Subject = subject;
            correo.Body = body;
            correo.IsBodyHtml = true;

            correo.Priority = MailPriority.Normal;

            SmtpClient smtp = new SmtpClient();
            smtp.Host = ConfigurationManager.AppSettings[DatosCorreo.EmailServer];

            smtp.Credentials = new NetworkCredential(ConfigurationManager.AppSettings[DatosCorreo.UserSmtp],
                ConfigurationManager.AppSettings[DatosCorreo.PwdSmtp]);

            try
            {
                smtp.Send(correo);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }        
        }

        
        /// <summary>
        /// Reemplaza los valores necesarios en un archivo html
        /// </summary>
        /// <param name="ruta"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static String GetHtml(string ruta, string[] parameters)
        {
            String strHtml = ReadFile(ruta);
            
            return null;           

        }

        /// <summary>
        /// Obtiene el menssaje del archivo XML según la clave especificada.
        /// </summary>
        /// <param name="idMessage"></param>
        /// <returns></returns>
        public static string GetMessage(string idMessage)
        {
            try
            {
                string lstrRuta = Convert.ToString(ConfigurationManager.AppSettings[Constantes.XmlPath]).Trim();
                XmlDocument xDoc = new XmlDocument();
                XmlTextReader reader;
                string valorMensaje = string.Empty;
                reader = new XmlTextReader(System.Web.HttpContext.Current.Server.MapPath(lstrRuta));

                bool sw = false;
                reader.WhitespaceHandling = WhitespaceHandling.None;
                reader.MoveToContent();

                while (reader.Read())
                {
                    if (reader.LocalName == Constantes.XmlMsgSubNode)
                    {
                        while (reader.Read())
                        {
                            if (reader.LocalName == Constantes.XmlMsgKey && reader.NodeType == XmlNodeType.Element)
                            {
                                reader.Read();
                                if (reader.Value == idMessage) sw = true;                                
                            }
                            if (sw && reader.LocalName == Constantes.XmlMsgValue && reader.NodeType == XmlNodeType.Element)
                            {
                                reader.Read();
                                valorMensaje = reader.Value;
                                reader.Close();
                                break;
                            }
                        }
                    }
                    reader.Close();
                }

                return valorMensaje;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }
                             
        /// <summary>
        /// Método que lee un archivo pasandole la ruta completa del archivo
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static String ReadFile(string path)
        {
            try
            {
                StreamReader strFile;
                String strText, strLine;
                strFile = File.OpenText(path);
                strText = string.Empty;
                strLine = strFile.ReadLine();
                while (strLine != null)
                {
                    strText = strText  + strLine;
                    strLine = strFile.ReadLine();
                }
                strFile.Close();
                return strText;
            }
            catch(Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }


        /// <summary>
        /// Convierte una fecha a letras
        /// </summary>
        /// <param name="fecha"></param>
        /// <returns></returns>
        public static string ConvertDateToLetters(DateTime fecha)
        {
            string[] meses = { "Enero", "Febreo", "Marzo", "Abril", "Mayo", "Junio",
                                 "Julio", "Agosto", "Setiembre", "Octubre", "Noviembre", "Diciembre" };

            int dia = fecha.Day;
            int mes = fecha.Month;
            int anio = fecha.Year;


            return dia + " de " + meses[mes - 1] + " del " + anio;
        }

        /// <summary>
        /// Graba el archivo
        /// </summary>
        /// <param name="file"></param>
        public static void GrabarArchivo(FileUpload fuFile, string file)
        {
            try
            {
                string ruta = ConfigurationManager.AppSettings[DatosConfiguracion.RutaFotos];

                if (File.Exists(ruta + file))
                {
                    File.Delete(ruta + file);
                }               

                if (fuFile.PostedFile.ContentLength > 1024*1024 * 0.3)
                {
                    byte[] img = ResizeImageFile(fuFile.FileBytes, 500, 400);
                    File.WriteAllBytes(ruta + file, img);
                }
                else 
                {
                    fuFile.PostedFile.SaveAs(ruta + file);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }        
        }

        /// <summary>
        /// Permite convertir un stream a un arreglo de bites
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] ReadToEnd(System.IO.Stream stream)
        {
            long originalPosition = stream.Position;
            stream.Position = 0;

            try
            {
                byte[] readBuffer = new byte[4096];

                int totalBytesRead = 0;
                int bytesRead;

                while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                {
                    totalBytesRead += bytesRead;

                    if (totalBytesRead == readBuffer.Length)
                    {
                        int nextByte = stream.ReadByte();
                        if (nextByte != -1)
                        {
                            byte[] temp = new byte[readBuffer.Length * 2];
                            Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                            Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                            readBuffer = temp;
                            totalBytesRead++;
                        }
                    }
                }

                byte[] buffer = readBuffer;
                if (readBuffer.Length != totalBytesRead)
                {
                    buffer = new byte[totalBytesRead];
                    Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                }
                return buffer;
            }
            finally
            {
                stream.Position = originalPosition;
            }
        }


        /// <summary>
        /// Graba el archivo
        /// </summary>
        /// <param name="file"></param>
        public static void GrabarArchivoSistema(FileUpload fuFile, string file, string tipo)
        {
            try
            {
                string ruta = ConfigurationManager.AppSettings[DatosConfiguracion.RutSistema];

                if (File.Exists(ruta + file))
                {
                    File.Delete(ruta + file);
                }

                if (tipo == ValidacionArchivo.TipoImagen)
                {
                    if (fuFile.PostedFile.ContentLength > 1024 * 1024 * 0.3)
                    {
                        byte[] img = ResizeImageFile(fuFile.FileBytes, 500, 400);
                        File.WriteAllBytes(ruta + file, img);
                    }
                    else
                    {
                        fuFile.PostedFile.SaveAs(ruta + file);
                    }
                }
                else 
                {
                    fuFile.PostedFile.SaveAs(ruta + file);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }


        /// <summary>
        /// Graba el archivo
        /// </summary>
        /// <param name="file"></param>
        public static void GrabarArchivoPDI(FileUpload fuFile, string file, string tipo)
        {
            try
            {
                string ruta = ConfigurationManager.AppSettings[DatosConfiguracion.RutaPDI];

                if (File.Exists(ruta + file))
                {
                    File.Delete(ruta + file);
                }

                if (tipo == ValidacionArchivo.TipoImagen)
                {
                    if (fuFile.PostedFile.ContentLength > 1024 * 1024 * 0.3)
                    {
                        byte[] img = ResizeImageFile(fuFile.FileBytes, 500, 400);
                        File.WriteAllBytes(ruta + file, img);
                    }
                    else
                    {
                        fuFile.PostedFile.SaveAs(ruta + file);
                    }
                }
                else
                {
                    fuFile.PostedFile.SaveAs(ruta + file);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Obtiene la ruta del PDI
        /// </summary>
        /// <returns></returns>
        public static string ObtenerRutaPDI()
        {
            string ruta = ConfigurationManager.AppSettings[DatosConfiguracion.RutaPDI];
            return ruta;
        }

        /// <summary>
        /// Elimina el archivo especificado fisicamente
        /// </summary>
        /// <param name="file"></param>
        public static void EliminarArchivo(string file)
        {
            try
            {
                string ruta = ConfigurationManager.AppSettings[DatosConfiguracion.RutaFotos];

                if (File.Exists(ruta + file))
                {
                    File.Delete(ruta + file);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Valida si existe o no un archivo
        /// </summary>
        /// <returns></returns>
        public static bool ValidarExistenciaArchivo(string file)
        {
            string ruta =  ConfigurationManager.AppSettings[DatosConfiguracion.RutaFotos];

            if (File.Exists(ruta + file))
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// Permite validar un archivo
        /// </summary>
        /// <returns></returns>
        public static string ValidarArchivo(FileUpload fuFile, string tipoFile)
        {
            if (string.IsNullOrEmpty(fuFile.FileName))
            {
                return ValidacionArchivo.ArchivoNoSeleccionado;
            }

            FileInfo fInfo = new FileInfo(fuFile.FileName);
            List<string> extensiones = new List<string>();
            extensiones.Add(".png"); extensiones.Add(".gif"); 
            extensiones.Add(".jpg"); extensiones.Add(".jpeg");
            extensiones.Add(".bmp");
            if (tipoFile != ValidacionArchivo.TipoImagen)
            {
                extensiones.Add(".xls"); extensiones.Add(".xlsx");
                extensiones.Add(".doc"); extensiones.Add(".docx");
                extensiones.Add(".ppt"); extensiones.Add(".pptx");
                extensiones.Add(".pdf"); 
            }
            
            if(!extensiones.Contains(fInfo.Extension.ToLower()))
            {
                return ValidacionArchivo.ExtensionNoPermitida;
            }

            if ((fuFile.PostedFile.ContentLength < 0) ||
               (fuFile.PostedFile.ContentLength > 1024 * 1024*15))
            {
                return ValidacionArchivo.PesoNoPermitido;
            }

            return ValidacionArchivo.OK;           

        }


        /// <summary>
        /// Valida que el archivo cargado sea excel
        /// </summary>
        /// <param name="ruta"></param>
        /// <param name="archivo"></param>
        /// <returns></returns>
        public static bool ValidarExcel(FileUpload file)
        {
            string extension;

            FileInfo infoFile;

            if (!string.IsNullOrEmpty(file.FileName))
            {
                infoFile = new FileInfo(file.FileName);
                extension = Convert.ToString(infoFile.Extension).Trim();

                if (extension.ToLower() == ".xls" || extension.ToLower() == ".xlsx")
                {
                    if ((file.PostedFile.ContentLength > 0) && (file.PostedFile.ContentLength <= 500 * 1024)) return true;

                    else return false;
                }
                else return false;
            }
            else return false;

            return true;
        }

        
        /// <summary>
        /// Valida que el archivo cargado sea excel
        /// </summary>
        /// <param name="ruta"></param>
        /// <param name="archivo"></param>
        /// <returns></returns>
        public static bool ValidarTXT(FileUpload file)
        {
            string extension;

            FileInfo infoFile;

            if (!string.IsNullOrEmpty(file.FileName))
            {
                infoFile = new FileInfo(file.FileName);
                extension = Convert.ToString(infoFile.Extension).Trim();

                if (extension.ToLower() == ".txt")
                {
                    if ((file.PostedFile.ContentLength > 0)) return true;

                    else return false;
                }
                else return false;
            }
            else return false;

            return true;
        }



        /// <summary>
        /// Permite redimensionar una imagen a los tamaños especificados
        /// </summary>
        /// <param name="imageFile"></param>
        /// <param name="targetW"></param>
        /// <param name="targetH"></param>
        /// <returns></returns>
        public static byte[] ResizeImageFile(byte[] imageFile, int targetW, int targetH)
        {            
            System.Drawing.Image original = System.Drawing.Image.FromStream(new MemoryStream(imageFile));

            float ag1 = (float)original.Height / (float)targetH;
            float ag2 = (float)original.Width / (float)targetW;

            if (ag1 == 1 && ag2 == 1)
            {
                return imageFile;
            }
            if (ag1 > ag2)
            {
                targetW = (int)(original.Width * ((float)targetH / (float)original.Height));
            }
            else
            {
                targetH = (int)(original.Height * ((float)targetW / (float)original.Width));
            }

            System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(new MemoryStream(imageFile));


            Bitmap bmPhoto = new Bitmap(targetW, targetH, original.PixelFormat);
            bmPhoto.SetResolution(original.HorizontalResolution, original.VerticalResolution);
            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.SmoothingMode = SmoothingMode.HighQuality;
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
            grPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;

            grPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, targetW, targetH), 0, 0, original.Width, original.Height, GraphicsUnit.Pixel);

            MemoryStream mm = new MemoryStream();
            bmPhoto.Save(mm, original.RawFormat);
            original.Dispose();
            imgPhoto.Dispose();
            bmPhoto.Dispose();
            grPhoto.Dispose();
            return mm.GetBuffer();
        }



        /// <summary>
        /// Verifica que las fecha02 sea mayor a la fecha01
        /// </summary>
        /// <param name="fecha01"></param>
        /// <param name="fecha02"></param>
        /// <returns></returns>
        public static bool ValidarFechas(DateTime fecha01, DateTime fecha02)
        {
            TimeSpan sp = fecha02 - fecha01;

            if (sp.TotalSeconds >= 0) return true;
            else return false;

        }


        /// <summary>
        /// Valida si he seleccionado un solo nodo y retorna el id seleccionado
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public static int ObtenerNodoRevursivo(TreeView tv, out int idPadre)
        {
            int contador = 0;
            int id = 0;
            foreach (TreeNode tn in tv.Nodes)
            {
                if (tn.Checked)
                {
                    contador++;
                    id = int.Parse(tn.Value);
                }

                if (tn.ChildNodes.Count > 0)
                {
                    foreach (TreeNode cTn in tn.ChildNodes)
                    {
                        contador = contador + ObtenerNodoHijoRecursivo(cTn, out idPadre);
                        if (idPadre > 0) id = idPadre;

                    }
                }
            }
            idPadre = id;
            return contador;
        }

        /// <summary>
        /// Verifica en forma recursiva la cantidad de elementos seleccionados en el treeview
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public static int ObtenerNodoHijoRecursivo(TreeNode tn, out int idPadre)
        {
            int contador = 0;
            int id = 0;
            if (tn.Checked)
            {
                contador++;
                id = int.Parse(tn.Value);                
            }
            if (tn.ChildNodes.Count > 0)
            {
                foreach (TreeNode tnC in tn.ChildNodes)
                {
                    contador = contador + ObtenerNodoHijoRecursivo(tnC, out idPadre);
                    if (idPadre > 0) id = idPadre;
                }
            }
            idPadre = id;
            return contador;
        }

        /// <summary>
        /// Retorna los elementos seleccionados de un treeview
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public static List<int> ObtenerNodoSeleccionados(TreeView tv)
        {
            List<int> list = new List<int>();

            foreach (TreeNode tn in tv.Nodes)
            {
                if (tn.Checked)
                {
                    list.Add(int.Parse(tn.Value));
                }

                if (tn.ChildNodes.Count > 0)
                {
                    foreach (TreeNode cTn in tn.ChildNodes)
                    {
                        list.AddRange(ObtenerNodoHijoRecursivo(cTn));


                    }
                }
            }

            return list;
        }

        /// <summary>
        /// Retorna los nodos hijos seleccionados de un treeview
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public static List<int> ObtenerNodoHijoRecursivo(TreeNode tn)
        {
            List<int> list = new List<int>();
            if (tn.Checked)
            {
                list.Add(int.Parse(tn.Value));
            }
            if (tn.ChildNodes.Count > 0)
            {
                foreach (TreeNode tnC in tn.ChildNodes)
                {
                    list.AddRange(ObtenerNodoHijoRecursivo(tnC));
                }
            }

            return list;
        }

        /// <summary>
        /// Obtiene el tipo de icono dependiendo de la clasificación del cliente
        /// </summary>
        /// <returns></returns>
        public static string ObtenerIconoMapa()
        {
            return null;
        }


        /// <summary>
        /// Retorna una lista html con los datos de la lista
        /// </summary>
        /// <param name="lista"></param>
        /// <returns></returns>
        public static string ObtieneListaHtml(List<string> list)
        {
            StringBuilder str = new StringBuilder();
            str.Append("<ul>");

            foreach (string item in list)
            {
                str.Append("    <li>" + item + "</li>");
            }

            str.Append("</ul>");

            return str.ToString();
        }

        /// <summary>
        /// Permite convertir el número en formato moneda
        /// </summary>
        /// <param name="monto"></param>
        /// <returns></returns>
        public static string ToMoneyFormat(decimal monto)
        {
            return monto.ToString("N", CultureInfo.InvariantCulture);
        }


        /// <summary>
        /// Permite obtener los emails válidos en una cadena
        /// </summary>
        /// <param name="texto"></param>
        /// <returns></returns>
        public static List<string> ObtenerEmailsValidos(string texto, out bool flag)
        {
            List<string> emailCC = new List<string>();
            flag = true;
            if (texto != "")
            {
                char[] delimiterChars = { ';' };
                string[] words = texto.Split(delimiterChars);

                string pattern = null;
                pattern = DatosCorreo.ValidarEmail;

                foreach (string s in words)
                {
                    if (Regex.IsMatch(s, pattern))
                    {
                        emailCC.Add(s);
                    }
                    else 
                    {
                        flag = false;
                    }
                }               
            }

            return emailCC;
        }
    }
}
